from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import String, Integer, Boolean, SmallInteger, ForeignKey, Column
from ..db import db
from typing import List
from ..utils.models import BaseModel

role_menu_m2m = db.Table(
    "role_menu",
    Column("role_id", ForeignKey("role.id"), primary_key=True),
    Column("menu_id", ForeignKey("menu.id"), primary_key=True)
)

role_permission_m2m = db.Table(
    "role_permission",
    Column("role_id", ForeignKey("role.id"), primary_key=True),
    Column("permission_id", ForeignKey("menu_button.id"), primary_key=True)
)


class Role(BaseModel):
    __tablename__ = "role"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    identity: Mapped[str] = mapped_column(String(32), comment="唯一标识")
    name: Mapped[str] = mapped_column(String(32), unique=True)
    user: Mapped[List["User"]] = relationship(back_populates="role")
    menu: Mapped[List['Menu']] = relationship(secondary=role_menu_m2m, back_populates="role")
    permission: Mapped[List['MenuButton']] = relationship(secondary=role_permission_m2m, back_populates="role")


class Menu(BaseModel):
    __tablename__ = "menu"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    identity: Mapped[str] = mapped_column(String(32), comment="唯一标识")
    path: Mapped[str] = mapped_column(String(256))
    name: Mapped[str] = mapped_column(String(32))
    redirect: Mapped[str] = mapped_column(String(256))
    menu_type: Mapped[int] = mapped_column(SmallInteger)
    icon: Mapped[str] = mapped_column(String(56))
    title: Mapped[str] = mapped_column(String(56))
    component: Mapped[str] = mapped_column(String(128))
    hidden_tag: Mapped[bool] = mapped_column(Boolean, default=False)
    keep_alive: Mapped[bool] = mapped_column(Boolean, default=False)
    frame_src: Mapped[str] = mapped_column(String(256), nullable=True)
    show_link: Mapped[str] = mapped_column(Boolean, default=True)
    show_parent: Mapped[str] = mapped_column(Boolean, default=True)
    svg: Mapped[str] = mapped_column(Boolean, default=False)
    svg_name: Mapped[str] = mapped_column(String(56), nullable=True)
    parent_id: Mapped[int] = mapped_column(ForeignKey('menu.id'), nullable=True)
    role: Mapped[List['Role']] = relationship(secondary=role_menu_m2m, back_populates="menu")
    menu_button: Mapped[List['MenuButton']] = relationship(back_populates='menu')

    def __repr__(self):
        return f"{self.title} -- {self.name}"

    @property
    def meta(self):
        data = {
            "title": self.title,
            "icon": self.icon,
            "hiddenTag": self.hidden_tag,
            "keepAlive": self.keep_alive,
            "showLink": self.show_link,
            "frameSrc": self.frame_src,
            "auths": []
        }

        if self.svg:
            data["extra_icon"] = {
                "svg": self.svg,
                "name": self.svg_name
            }
        return data

    @property
    def to_dict(self):
        return {
            "id": self.id,
            "identity": self.identity,
            "name": self.name,
            "path": self.path,
            "meta": self.meta,
            "parent_id": self.parent_id,
        }


class MenuButton(BaseModel):
    __tablename__ = "menu_button"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    menu_id: Mapped[int] = mapped_column(ForeignKey("menu.id"), primary_key=True)
    menu: Mapped['Menu'] = relationship(back_populates="menu_button")
    name: Mapped[str] = mapped_column(String(32))
    value: Mapped[str] = mapped_column(String(64))
    api: Mapped[str] = mapped_column(String(200))
    method: Mapped[int] = mapped_column(SmallInteger)
    role: Mapped[List['Role']] = relationship(secondary=role_permission_m2m, back_populates="permission")

    def __repr__(self):
        return f"{self.name}--{self.api} "
